SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00002 1 05-25-9408:13ALL DAVID KANDRAT pgdn/pgup SWAG9405 15 π{πHere is an (TP 5.5) atom that will help you grab "extended"πkeyboard scancodes. I think the problem you're having has toπdo with the fact that you can't trap hot keys inside ReadLn,πyes? You need to build a set of routines that supportπa-key-at-a-time input into a string, echoing the keystrokesπto the screen as you go. This "atom" just handles keystrokes-πthe string handling is probably _WAY_ too long to list here.π}ππProgram _;ππUses Crt;ππType KeyType = (Ascii,ExtendedKey,Escape);ππVarπKtGlb : KeyType;πChGlb : Char;ππProcedure GetExtKey( Var Ch:Char; Var Kt:KeyType; );πBeginπ Repeatπ Until KeyPressed;π Kt := Ascii;π Ch := ReadKey;π If (Ch=#0) Thenπ Beginπ Ch := ReadKey;π If (Ord(Ch)=27) Then Kt := Escape Else Kt := ExtendedKey;π End;πEnd;ππProcedure MainπBeginπ Write('Press a key.');π ChGlb := #0;π KtGlb := Ascii;π Repeatπ GotoXY(13,1);π GetExtKey(ChGlb,KtGlb);π GotoXY(1,2);π ClrEol;π GotoXY(1,2);π Case KtGlb Ofπ Ascii : Write('Ascii, ');π ExtendedKey : Write('Extended, ');π Escape : Write('Escape, ')π End;π Write('Scancode = ',Ord(Ch));π Until (Kt=Escape);π WriteLn;π WriteLn;πEnd;ππBeginπ ClrScr;π Main;πEnd.ππThis should help you capture _any_ extended scan code from the keyboard.πPgUp, PgDn, Ctrl-PgUp, Alt-Shft-F5, etc... Chapter Seventeen of "TurboπPascal 5.5, The Complete Reference" by O'Brien (Borland/Osborne/McGraw-πHill ISBN 0-07-881501-0) covers the issue of buffered string input prettyπwell.ππAnd as for your next berrage of questions, "Turbo Pascal AdvancedπTechniques" by Ohlsen & Stoker (Que Corp. ISBN 0-88022-432-0) coversπDOS windowing very nicely. (Also many other goodies).ππHope it helped a little.πDavid Kandratπ 2 05-26-9406:11ALL JEFF FANJOY Key Input Unit SWAG9405 100 UNIT KeyInput;ππINTERFACEππUSES CRT, {Import Sound function}π CURSOR; {Import ChangeCursor}ππCONSTπ StandardInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&*()-+\[]{};:`''".,/<> =_?|';π HighBitInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&*()-+\[]{};:`''".,/<> =_?|'π +'ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«'π +'»░▒▓│┤╡╢║╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐'π +'▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■';π FilenameInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&()-_{}.';π FilespecInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&()-_{}.?*';π FilepathInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&()-_{}.?*:\';π NumberInput = '123456790.-+';ππ BackSpace = #8;π Space = ' ';πππTYPEπ TInput = (Standard,HighBit,Filename,Filespec,Filepath,Number);πππVARπ MaskCh: Char; {must be set before using}πππPROCEDURE GetInput(VAR InStr; (* Variable being edited *)π WhatWas: String; (* "Old" Value -- being edited *)π InputType: TInput; (* Input type -- from TInput *)π Len, (* Maximum Characters *)π XPos, (* X Start Position *)π YPos, (* Y Start Position *)π Attr, (* Text Attribute while editing *)π HighLightAttr: Byte; (* Attribute of Highlighted Text *)π BackCh: Char; (* Background Character *)π MaskInput, (* Masked Input? -- Set "MaskCh" *)π Caps: Boolean); (* Force CAPS? *)πππIMPLEMENTATIONπππPROCEDURE MY_Delay(MS: Word); Assembler;π (* My Delay procedure, used instead of TP6.0's Delay procedure *)ππASMπ MOV Ax, 1000;π MUL MS;π MOV Cx, Dx;π MOV Dx, Ax;π MOV Ah, $86;π INT $15;πEND;πππPROCEDURE GetInput(VAR InStr;π WhatWas: String;π InputType: TInput;π Len,π XPos,π YPos,π Attr,π HighLightAttr: Byte;π BackCh: Char;π MaskInput,π Caps: Boolean);ππTYPEπ TInsert = (On,Off); (* Insert On/Off Type *)ππVARπ Temp: String; (* Temporary String Holder *)π Ch: Char; (* Reads Characters *)π A, B, U: Byte; (* Counters *)π ValidKey, (* Whether is valid key *)π FirstChar, (* Whether is first char entered *)π InsertOn, (* Insert or overstrike mode *)π NoAdd: Boolean; (* Whether to add key to string *)π NewString: String ABSOLUTE InStr; (* String being edited *)πππ PROCEDURE Ding;π (* Makes sound to tell user invalid key was pressed *)ππ BEGINπ Sound(300);π MY_Delay(30);π NoSound;π END;πππ PROCEDURE ToggleInsert(Ins: TInsert);π (* Toggles Insert/Overstrike Mode via TInsert type *)ππ BEGINπ IF Ins = On THENπ BEGINπ InsertOn := TRUE;π ChangeCursor(NormCursor);π ENDπ ELSEπ BEGINπ InsertOn := FALSE;π ChangeCursor(BlockCursor);π END;π END;πππ PROCEDURE FlushKBuff;π (* Flush keyboard buffer *)π VAR Flush: Char;ππ BEGINπ WHILE KeyPressed DO Flush := Readkey;π END;πππBEGINπ ChangeCursor(NormCursor); (* Default to normal cursor *)π InsertOn := TRUE; (* Default to Insert Mode *)π FirstChar := TRUE; (* Set to first character being entered *)π NewString := ''; (* Null NewString *)π Temp := ''; (* Null Temporary String *)π GotoXY(XPos,YPos);π TextAttr := Attr;π FOR U := 1 TO Len DO Write(BackCh);π GotoXY(XPos,YPos);π FlushKBuff;π Ch := #0;π TextAttr := HighLightAttr;π NewString := WhatWas;π IF MaskInput THEN FOR U := 1 TO Length(NewString) DO Write(MaskCh)π ELSE Write(NewString);π B := Length(WhatWas);π A := B;π (* "A" Counter = How many characters are in string *)π (* "B" Counter = Current cursor placement in string *)π TextAttr := Attr;π WHILE (Ch <> #13) AND (Ch <> #27) DOπ BEGINπ NoAdd := FALSE; (* Default to add key to string *)π ValidKey := FALSE; (* Default to invalid key unless proven valid *)π IF Caps THEN Ch := UpCase(ReadKey)π ELSE Ch := ReadKey;π CASE InputType OF (* Check if Ch is in the input list *)π Standard: IF (POS(Ch,StandardInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π HighBit : IF (POS(Ch,HighBitInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Filename: IF (POS(Ch,FilenameInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Filespec: IF (POS(Ch,FilespecInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Filepath: IF (POS(Ch,FilepathInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Number : IF (POS(Ch,NumberInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π END;π IF ValidKey THENπ BEGINπ CASE Ch OFπ #0 : BEGINπ NoAdd := TRUE;π IF FirstChar THENπ BEGINπ FirstChar := FALSE;π GotoXY(XPos,YPos);π IF MaskInput THEN FOR U := 1 TO Length(NewString) DO Write(MaskCh)π ELSE Write(NewString);π END;π Ch := UpCase(ReadKey);π CASE Ch OFπ #77: IF B <= Length(NewString)-1 THEN {Right Arrow}π BEGINπ GotoXY(XPos+B+1,YPos);π Inc(B);π ENDπ ELSE Ding;π #75: IF B >= 1 THEN {Left Arrow}π BEGINπ GotoXY(XPos+B-1,YPos);π Dec(B);π ENDπ ELSE Ding;π #71: BEGIN {Home}π GotoXY(XPos,YPos);π B := 0;π END;π #79: BEGIN {End}π GotoXY(XPos+Length(NewString),YPos);π B := Length(NewString);π END;π #82: IF InsertOn THEN ToggleInsert(Off) {Ins}π ELSE ToggleInsert(On);π #83: BEGIN {Del}π IF (B < Length(NewString)) AND (B >= 0) THENπ BEGINπ Delete(NewString,B+1,1);π FOR U := B TO Length(NewString) DOπ IF MaskInput THENπ BEGINπ IF U <> B THEN Temp := Temp + MaskChπ ELSE Temp := '';π ENDπ ELSEπ BEGINπ IF U <> B THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π GotoXY(XPos+B,YPos);π Write(Temp);π Write(BackCh);π GotoXY(XPos+B,YPos);π Dec(A);π END;π END;π ELSE Ding;π END;π FlushKBuff;π END;π #8 : IF B >= 1 THEN {Backspace}π BEGINπ IF FirstChar THENπ BEGINπ FirstChar := FALSE;π GotoXY(XPos,YPos);π IF MaskInput THEN FOR U := 1 TO Length(NewString) DO Write(MaskCh)π ELSE Write(NewString);π END;π Delete(NewString,B,1);π Write(Backspace,BackCh,Backspace);π Dec(B);π Dec(A);π GotoXY(XPos+B,YPos);π FOR U := B TO Length(NewString) DOπ IF MaskInput THENπ BEGINπ IF B <> U THEN Temp := Temp + MaskChπ ELSE Temp := '';π ENDπ ELSEπ BEGINπ IF B <> U THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π Write(Temp);π FOR U := Length(NewString)+1 TO Len DO Write(BackCh);π GotoXY(XPos+B,YPos);π NoAdd := TRUE;π ENDπ ELSE Ding;π #27: BEGIN {Esc}π NoAdd := TRUE;π NewString := WhatWas;π END;π #25: BEGIN {CTRL+Y}π NoAdd := TRUE;π NewString := '';π GotoXY(XPos,YPos);π FOR U := 1 TO Len DO Write(BackCh);π FirstChar := FALSE;π GotoXY(XPos,YPos);π B := 0;π A := 0;π END;π #13: NoAdd := TRUE;π END;π IF (((A < Len) OR ((A < Len+1) AND NOT(InsertOn))) AND (NoAdd = FALSE)π AND (Ch <> #8)) OR ((FirstChar) AND (NOT(NoAdd)) AND (Ch <> #8)) THENπ BEGINπ IF FirstChar THENπ BEGINπ NewString := '';π GotoXY(XPos,YPos);π B := 0;π A := 0;π FOR U := 1 TO Len Do Write(BackCh);π GotoXY(XPos,YPos);π FirstChar := FALSE;π END;π IF InsertOn THENπ BEGINπ Inc(B);π Inc(A);π Insert(Ch,NewString,B);π FOR U := B TO Length(NewString) DOπ IF MaskInput THENπ BEGINπ IF B <> U THEN Temp := Temp + MaskChπ ELSE Temp := '';π ENDπ ELSEπ BEGINπ IF B <> U THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π GotoXY(XPos+B-1,YPos);π IF MaskInput THEN Write(MaskCh)π ELSE Write(Ch);π Write(Temp);π GotoXY(XPos+B,YPos);π ENDπ ELSEπ BEGINπ IF Length(NewString) < Len THENπ BEGINπ IF B >= Length(NewString) THEN Inc(A);π Inc(B);π Delete(NewString,B,1);π Insert(Ch,NewString,B);π IF MaskInput THEN Write(MaskCh)π ELSE Write(Ch);π ENDπ ELSE IF (A = Len) AND (B < Len) THENπ BEGINπ Inc(B);π Delete(NewString,B,1);π Insert(Ch,NewString,B);π IF MaskInput THEN Write(MaskCh)π ELSE Write(Ch);π END;π END;π END;π ENDπ ELSE Ding;π END;π FlushKBuff;π ChangeCursor(NormCursor);πEND;πππEND.ππ